<script setup lang="ts">
import { ref, reactive, unref, computed, PropType, watch } from "vue";
import type {
  UploadInstance,
  UploadProps,
  UploadUserFile,
  UploadRawFile,
} from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { propTypes } from "@/utils/propTypes";
import { securityToken } from "@/api/common";
import OSS from "ali-oss";

const props = defineProps({
  defaultList: propTypes.array.def([]),
  size: propTypes.number.def(500),
  fileType: propTypes.array.def(["png", "jpg", "xls"]),
  limit: propTypes.number.def(1),
});

interface fileListType {
  name: string;
  uid: string | number;
  url: string;
  row?: Object;
}

const fileList = ref([]);
const client = ref({});
const upload = ref<UploadInstance>();

// 默认文件数据
watch(
  () => props.defaultList,
  (newValue, oldValue) => {
    console.log("默认文件数据", newValue, oldValue);
    if (newValue && newValue.length) {
      newValue.forEach((item: any) => {
        console.log("默认文件数据item", item);
        const objectName = item?.split("/").slice(3).join("/");
        const obj = {
          name: objectName,
          objectName: objectName,
          uid: objectName,
          url: item,
        };
        fileList.value.push(obj);
      });
    }
  },
  { immediate: true }
);

//文件上传
const upFile = async () => {
  const { data: upToken } = await securityToken();
  console.log("upToken", upToken);
  client.value = new OSS({
    region: "oss-cn-shanghai",
    secure: true,
    accessKeyId: upToken.accessKeyId,
    accessKeySecret: upToken.accessKeySecret,
    stsToken: upToken.securityToken,
    bucket: "ta-tech-image",
  });

  console.log("待上传文件", fileList.value);
  const upFileFun = fileList.value
    .filter((item) => item.raw)
    .map((item: any) => {
      return uploadOss(item.raw);
    });

  await Promise.all(upFileFun);
  return fileList.value.map((item) => {
    return item.objectName;
  });
};

// 上传具体 方法
const uploadOss = (file) => {
  return new Promise((resolve, reject) => {
    const randomString = Math.random().toString(36).slice(2);
    const suffix = /\.[^\.]+/.exec(file.name);
    const timestamp = new Date().getTime();
    const objectName = `imagedir/${randomString}_${timestamp}${suffix}`;
    client.value
      .put(objectName, file)
      .then((res) => {
        const index = fileList.value.findIndex((list) => list.uid === file.uid);
        fileList.value[index].objectName = objectName;
        console.log(res, fileList);
        resolve();
      })
      .catch((err) => {
        resolve("error");
        console.log(err);
      });
  });
};

const handleExceed: UploadProps["onExceed"] = (files, uploadFiles) => {
  upload.value!.clearFiles();
  const file = files[0] as UploadRawFile;
  upload.value!.handleStart(file);
};

const beforeRemove: UploadProps["beforeRemove"] = (uploadFile, uploadFiles) => {
  return ElMessageBox.confirm(`确认删除 ${uploadFile.name} ?`).then(
    () => true,
    () => false
  );
};

// 获取表单传输对象
const getProps = computed(() => {
  const propsObj = { ...props };
  Object.assign({}, propsObj);
  console.log("获取表单对象", propsObj);
  return propsObj;
});

// 提示文案
const tips  =  computed(()=>{
  return '支持拓展名：'+ props.fileType.join('、') + ' 文件大小：'+props.size
})

// 文件上传修改
const handleChange: UploadProps["onChange"] = (uploadFile, uploadFiles) => {
  console.log("上传文件变更", uploadFile, uploadFiles, uploadFile.raw!);

  // 上传的图片格式判断
  const typeResult = verificationPicType(uploadFile);
  if (!typeResult) return;
};
/**
 * 上传的图片格式判断
 * @param {blob} file: 上传的图片文件
 * @returns {boolean} 验证结果
 */
const verificationPicType = (file: any) => {
  if (!file.raw) return false;
  const { fileType, size } = unref(getProps);
  //格式类型
  var fileTypes = fileType; // 图片限制的格式类型
  const type = file.name.slice(file.name.lastIndexOf(".") + 1);
  const isType = fileTypes.includes(type.toLowerCase());
  if (!isType) {
    ElMessage.warning("当前仅支持格式为：" + fileTypes.join(" ，"));
    return false;
  }
  //判断size
  const unit = file.name.includes("K") ? "K" : "M";
  const result = verificationPicSize(file.raw, file.zise, unit);
  if (!result) {
    ElMessage.warning("请上传文件小于" + size + "的文件!");
    return false;
  } else {
    return true;
  }
};

/**
 * 上传的图片大小判断
 * @param {blob} file: 上传的图片文件
 * @param {number} limit: size限制
 * @param {string} unit: size单位
 * @returns {boolean} 验证结果
 */
const verificationPicSize = (file: File, limit: number, unit: string): boolean => {
  if (!file || !limit || !unit) return false;

  if (unit == "K") {
    if (file.size / 1024 > limit) {
      return false;
    } else {
      return true;
    }
  } else if (unit == "M") {
    if (file.size / 1024 / 1024 > limit) {
      return false;
    } else {
      return true;
    }
  } else {
    return false;
  }
};

/**
 * 上传的图片尺寸校验
 * @param {blob} file: 上传的图片文件
 * @param {number} imgWidth: 图片宽度
 * @param {number} imgHeight: 图片高度
 * @returns {boolean|Promise} 验证结果
 */
const verificationPicPx = (file: Blob, imgWidth: number, imgHeight: number) => {
  if (!file || !imgWidth || !imgHeight) return false;
  // 获取文件尺寸，判断尺寸在不在规定范围之内
  return new Promise(function (resolve, reject) {
    let reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = function (theFile: any) {
      const image = new Image();
      image.src = theFile.target?.result;
      image.onload = function (res: any) {
        if (res.target.width !== imgWidth || res.target.height !== imgHeight) {
          resolve(false);
        } else {
          resolve(true);
        }
      };
    };
  });
};


const uploadFun = async () => {
  const files = await upFile();
  return files;
};

defineExpose({
  uploadFun,
});
</script>

<template>
  <el-upload
    ref="upload"
    v-model:file-list="fileList"
    class="upload-demo"
    multiple
    :before-remove="beforeRemove"
    :on-change="handleChange"
    :limit="props.limit"
    :auto-upload="false"
    :on-exceed="handleExceed"
  >
    <el-button type="primary" size="small">上传</el-button>
    <template #tip>
      <div class="el-upload__tip upload__tip"> {{tips}}</div>
    </template>
  </el-upload>
</template>
<style lang="less" scoped>
.upload__tip {
  float: right;
  margin: 0;
  margin-left: 15px;
}
</style>
